package com.huilian.iotbox.data.service.impl;

import com.alibaba.fastjson.JSON;
import com.huilian.iotbox.data.dao.OrderItemCommonDao;
import com.huilian.iotbox.data.enums.*;
import com.huilian.iotbox.data.po.*;
import com.huilian.iotbox.data.service.*;
import com.huilian.iotbox.data.utils.SciCalUtils;
import com.huilian.iotbox.data.vo.LedgerMerchantRecordVo;
import com.huilian.iotbox.data.vo.MerchantStoreVo;
import com.huilian.iotbox.data.vo.OrderItemVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class ShareCommonServiceImpl implements ShareCommonService {
    @Autowired
    private OrderItemCommonDao orderItemCommonDao;
    @Autowired
    private LedgerOrderCommonService ledgerOrderCommonService;
    @Autowired
    private MerchantStoreCommonService merchantStoreCommonService;
    @Autowired
    private LedgerMerchantCommonService ledgerMerchantCommonService;
    @Autowired
    private LedgerCommodityCommonService ledgerCommodityCommonService;
    @Autowired
    private CommodityStoreUpDownCommonService commodityStoreUpDownCommonService;
    @Autowired
    private LedgerMerchantRecordCommonService ledgerMerchantRecordCommonService;

    @Override
    public synchronized JsPay divideAccounts(
            int ledgerOrderType,
            BigDecimal totalAmount,
            int userId,
            int merchantStoreId,
            String baseMerchantId,
            long orderIdOrActivityOrderId
    ) {
        log.info("ledgerOrderType：{}", ledgerOrderType);
        log.info("totalAmount：{}", totalAmount);
        log.info("userId：{}", userId);
        log.info("merchantStoreId：{}", merchantStoreId);
        log.info("baseMerchantId：{}", baseMerchantId);
        log.info("orderIdOrActivityOrderId：{}", orderIdOrActivityOrderId);
        if (StringUtils.isEmpty(baseMerchantId)) {
            throw new RuntimeException("主商户不能为空");
        }

        LedgerMerchant ledgerMerchantCondition = new LedgerMerchant();
        ledgerMerchantCondition.setMerchantStoreId(merchantStoreId);
        final LedgerMerchant ledgerMerchant = ledgerMerchantCommonService.findOneByMerchantStoreIdAndFailureStatus(ledgerMerchantCondition);

        // 分账金额
        BigDecimal shareAmount = BigDecimal.ZERO;
        // 不分账金额
        BigDecimal notShareAmount = BigDecimal.ZERO;
        // 商户配置的分账商户
        List<LedgerMerchantRecordVo> ledgerMerchantRecordList = new ArrayList<>();
        if (!StringUtils.isEmpty(ledgerMerchant)) {

            log.info("分账-订单金额：{}", totalAmount);

            if (ledgerMerchant.getDesignatedGoods()) {
                // 指定商品分账

                /**
                 * 购买商品全部在分账范围
                 * 购买商品部分在分账范围
                 * 购买商品全部不在分账范围
                 */
                //查询订单记录
                List<OrderItemVo> orderItemVoList;
                if (LedgerOrderTypeEnum.ORDER.getCode().compareTo(ledgerOrderType) == 0) {
                    orderItemVoList = orderItemCommonDao.findOrderItemByOrderIdList(orderIdOrActivityOrderId);
                } else if (LedgerOrderTypeEnum.ACTIVITY_ORDER.getCode().compareTo(ledgerOrderType) == 0) {
                    orderItemVoList = new ArrayList<>();
                    shareAmount = totalAmount;
                } else {
                    throw new RuntimeException("ledgerOrderType有误");
                }

                for (OrderItemVo orderItemVo : orderItemVoList) {
                    if (StringUtils.isEmpty(orderItemVo.getCommodityStoreUpDownId())) {
                        throw new RuntimeException("商品上下架ID不能为空");
                    }
                    CommodityStoreUpDown commodityStoreUpDownCondition = new CommodityStoreUpDown();
                    commodityStoreUpDownCondition.setId(orderItemVo.getCommodityStoreUpDownId());
                    final CommodityStoreUpDown commodityStoreUpDown = commodityStoreUpDownCommonService.findOneCommodityStoreUpDownByCondition(commodityStoreUpDownCondition);
                    if (StringUtils.isEmpty(commodityStoreUpDown)) {
                        log.error("commodityStoreUpDownId：{}商品已下架，请刷新商品列表重新下单", orderItemVo.getCommodityStoreUpDownId());
                        throw new RuntimeException("部分商品已下架，请刷新商品列表重新下单");
                    }

                    if (LedgerMerchantDesignatedGoodsTypeEnum.ALL_GOODS.getCode().equals(ledgerMerchant.getDesignatedGoodsType())) {

                    } else if (LedgerMerchantDesignatedGoodsTypeEnum.PARTIAL_GOODS.getCode().equals(ledgerMerchant.getDesignatedGoodsType())) {
                        final LedgerCommodity ledgerCommodity = ledgerCommodityCommonService.findOneByCommodityAndLedgerMerchantId(commodityStoreUpDown.getCommodityId(), ledgerMerchant.getId());
                        if (StringUtils.isEmpty(ledgerCommodity)) {
                            log.warn("当前商品不在分账范围内");
                            notShareAmount = notShareAmount.add(commodityStoreUpDown.getRetailPrice().multiply(BigDecimal.valueOf(orderItemVo.getNum())));
                            continue;
                        }
                    } else {
                        throw new RuntimeException("分账商品范围有误");
                    }

                    // 同款商品总金额（单价 * 数量）
                    BigDecimal identicalProductTotalAmount = commodityStoreUpDown.getRetailPrice().multiply(BigDecimal.valueOf(orderItemVo.getNum()));
                    if (ledgerMerchant.getRemovalCost()) {
                        // 去除成本后再进行分账

                        // 计算同款商品总成本
                        final BigDecimal totalCostPrice = commodityStoreUpDown.getCostPrice().multiply(BigDecimal.valueOf(orderItemVo.getNum()));

                        // 累加分账总金额 = 同款商品总金额 - 同款商品成本
                        shareAmount = shareAmount.add(identicalProductTotalAmount.subtract(totalCostPrice));

                        // 累加不分账总金额 += 同款商品成本
                        notShareAmount = notShareAmount.add(totalCostPrice);
                    } else {
                        shareAmount = shareAmount.add(identicalProductTotalAmount);
                    }
                }
            } else {
                shareAmount = totalAmount;
            }

            LedgerMerchantRecord ledgerMerchantRecordCondition = new LedgerMerchantRecord();
            ledgerMerchantRecordCondition.setLedgerMerchantId(ledgerMerchant.getId());
            ledgerMerchantRecordCondition.setType(LedgerMerchantRecordTypeEnum.CLOSE.getCode());
            //分账商户信息
            ledgerMerchantRecordList = ledgerMerchantRecordCommonService.findAllByCondition(ledgerMerchantRecordCondition);
        } else {
            shareAmount = totalAmount;
        }

        List<SplitInfo> acctInfos = new ArrayList<>();
        List<LedgerOrder> ledgerOrderList = new ArrayList<>();

        LedgerOrder ledgerOrderTemp = new LedgerOrder();
        if (LedgerOrderTypeEnum.ORDER.getCode().compareTo(ledgerOrderType) == 0) {
            ledgerOrderTemp.setOrderId(orderIdOrActivityOrderId);
        } else if (LedgerOrderTypeEnum.ACTIVITY_ORDER.getCode().compareTo(ledgerOrderType) == 0) {
            ledgerOrderTemp.setActivityOrderId(orderIdOrActivityOrderId);
        } else {
            throw new RuntimeException("ledgerOrderType有误_2");
        }
        ledgerOrderTemp.setUserId(userId);
        ledgerOrderTemp.setMerchantStoreId(merchantStoreId);
        ledgerOrderTemp.setOrderType(ledgerOrderType);


        if (ledgerMerchantRecordList.size() == 0) {
            log.info("订单：{}不需要营业额分账、抖音美团手续费分账", orderIdOrActivityOrderId);
            return null;
        }

        // 分账总金额，每个分账商户累加
        BigDecimal splitTotalAccountMoney = BigDecimal.ZERO;

        // 可分账金额减去 抖音美团手续费分账金额
        shareAmount = shareAmount.subtract(BigDecimal.ZERO);

        //添加分账收益
        log.info("---------------分账商户-BEGIN-----------------");
        // 分账金额
        final BigDecimal shareAmountBase = shareAmount;
        for (LedgerMerchantRecordVo lmrVo : ledgerMerchantRecordList) {
            log.info("分账-分账商户{},分账比例：{}%", lmrVo.getMerchantNo(), lmrVo.getShareRate());
            // 分账商户开始分账
            BigDecimal price = shareAmountBase.multiply(lmrVo.getShareRate().divide(BigDecimal.valueOf(100))).setScale(2, BigDecimal.ROUND_HALF_UP);
            BigDecimal handlingCharge = BigDecimal.ZERO;
            log.info("分账-分账商户{},预计分账金额：{}", lmrVo.getMerchantNo(), price);
            if (price.compareTo(BigDecimal.valueOf(0.01)) == -1) {
                continue;
            }

            shareAmount = shareAmount.subtract(price);
            log.info("分账-分账商户{},实际分账金额：{}", lmrVo.getMerchantNo(), price);
            splitTotalAccountMoney = splitTotalAccountMoney.add(price);

            LedgerOrder ledgerOrderFirst = new LedgerOrder();
            BeanUtils.copyProperties(ledgerOrderTemp, ledgerOrderFirst);
            ledgerOrderFirst.setMerchantId(lmrVo.getMerchantId());
            ledgerOrderFirst.setMoney(price);
            ledgerOrderFirst.setHandlingCharge(handlingCharge);
            ledgerOrderFirst.setRate(lmrVo.getShareRate().divide(BigDecimal.valueOf(100)));
            ledgerOrderFirst.setLedgerType(LedgerOrderLedgerTypeEnum.GENERAL_LEDGER.getCode());
            ledgerOrderList.add(ledgerOrderFirst);

            acctInfos.add(new SplitInfo(String.valueOf(price.multiply(new BigDecimal("100")).setScale(0, BigDecimal.ROUND_HALF_UP)), lmrVo.getMerchantNo()));
        }
        log.info("---------------分账商户-END-----------------");


        log.info("---------------主商户-BEGIN-----------------");
        if (!StringUtils.isEmpty(ledgerMerchant)) {
            LedgerMerchantRecord ledgerMerchantRecordBaseCondition = new LedgerMerchantRecord();
            ledgerMerchantRecordBaseCondition.setLedgerMerchantId(ledgerMerchant.getId());
            ledgerMerchantRecordBaseCondition.setType(LedgerMerchantRecordTypeEnum.START.getCode());
            final List<LedgerMerchantRecordVo> ledgerMerchantRecordBaseList = ledgerMerchantRecordCommonService.findAllByCondition(ledgerMerchantRecordBaseCondition);
            if (StringUtils.isEmpty(ledgerMerchantRecordBaseList.size())) {
                throw new RuntimeException("主商户信息不存在_1");
            }
            if (ledgerMerchantRecordBaseList.size() == 0) {
                throw new RuntimeException("主商户信息不存在_2");
            }
            if (ledgerMerchantRecordBaseList.size() > 1) {
                throw new RuntimeException("主商户信息不存在_3");
            }

            final LedgerMerchantRecordVo ledgerMerchantRecordBaseVo = ledgerMerchantRecordBaseList.get(0);
            if (!baseMerchantId.equals(ledgerMerchantRecordBaseVo.getMerchantNo())) {
                throw new RuntimeException("商户号前后不一致，请与平台联系");
            }

            LedgerOrder ledgerOrderSecond = new LedgerOrder();
            BeanUtils.copyProperties(ledgerOrderTemp, ledgerOrderSecond);
            ledgerOrderSecond.setMerchantId(ledgerMerchantRecordBaseVo.getMerchantId());
            ledgerOrderSecond.setMoney(shareAmount.add(notShareAmount));
            ledgerOrderSecond.setCostAmount(notShareAmount);
            ledgerOrderSecond.setRate(ledgerMerchantRecordBaseVo.getShareRate().divide(BigDecimal.valueOf(100)));
            ledgerOrderSecond.setLedgerType(LedgerOrderLedgerTypeEnum.GENERAL_LEDGER.getCode());
            ledgerOrderList.add(ledgerOrderSecond);

            acctInfos.add(new SplitInfo(String.valueOf((ledgerOrderSecond.getMoney()).multiply(new BigDecimal("100")).setScale(0, BigDecimal.ROUND_HALF_UP)), ledgerMerchantRecordBaseVo.getMerchantNo()));
        }
        log.info("---------------主商户-END-----------------");


        log.info("---------------插入分账订单记录-BEGIN-----------------");
        for (LedgerOrder ledgerOrder : ledgerOrderList) {
            log.info(JSON.toJSONString(ledgerOrder));
            if (StringUtils.isEmpty(ledgerMerchant) && LedgerOrderLedgerTypeEnum.GENERAL_LEDGER.getCode().equals(ledgerOrder.getLedgerType())) {
                // 当只有主商户和系统商户分账时，只插入系统商户分账记录
                log.warn("当只有主商户和系统商户分账时，只插入系统商户分账记录");
                continue;
            }
            Integer row = ledgerOrderCommonService.inset(ledgerOrder);
            if (row == 0) {
                log.error("分账订单记录插入失败");
            }
        }
        log.info("---------------插入分账订单记录-END-----------------");


        log.info("---------------组装最终分账串-BEGIN-----------------");
        SplitBunch splitBunch = new SplitBunch(String.valueOf(acctInfos.size()), baseMerchantId, acctInfos);

        JsPay jsPay = new JsPay();
        jsPay.setSplitBunch(splitBunch.genJsonBase64());
        log.info("---------------组装最终分账串-BEGIN-----------------");


        log.info("shareAmount：{}", shareAmount);
        log.info("notShareAmount：{}", notShareAmount);
        log.info("tAmount：{}", notShareAmount.add(shareAmount));
        log.info("totalAmount：{}", totalAmount);

        return jsPay;
    }

    public static void main(String[] args) {
        List<LedgerOrder> ledgerOrderList = new ArrayList<>();

        LedgerOrder ledgerOrderTemp = new LedgerOrder();
        ledgerOrderTemp.setOrderId(1l);
        ledgerOrderTemp.setUserId(39);
        ledgerOrderTemp.setMerchantStoreId(5276);
        ledgerOrderTemp.setOrderType(1);

        LedgerOrder ledgerOrderSecond = new LedgerOrder();
        BeanUtils.copyProperties(ledgerOrderTemp, ledgerOrderSecond);
        ledgerOrderSecond.setLedgerType(LedgerOrderLedgerTypeEnum.GENERAL_LEDGER.getCode());
        ledgerOrderList.add(ledgerOrderSecond);


        LedgerOrder ledgerOrderSecond2 = new LedgerOrder();
        BeanUtils.copyProperties(ledgerOrderTemp, ledgerOrderSecond2);
        ledgerOrderSecond2.setLedgerType(LedgerOrderLedgerTypeEnum.TIKTOK_MEITUAN_CANCELLATION_FEE.getCode());
        ledgerOrderList.add(ledgerOrderSecond2);


        for (LedgerOrder ledgerOrder : ledgerOrderList) {
            log.info(ledgerOrder.getLedgerType() + "");
        }
    }
}
